#ifndef router_h__
#define router_h__

#include "common.h"
#include <functional>
#include <mutex>

#include "boost/regex.hpp"

#include "response.h"
#include "request.h"


typedef std::function<void(const request& req, response& res)> http_handler_t;
struct router_child
{
	typedef boost::shared_ptr<router_child> ptr;
public:
	router_child(const char* name, boost::regex rgx, http_handler_t cb):
	_child(name),
	_rgx(rgx),
	_cb(cb)
	{

	}

	bool rout(std::string& url)
	{
		return boost::regex_match(url, _rgx);
	}
	void operator()(const request& req, response& res)
	{
		_cb(req, res);
	}
private:
	std::string _child;
	boost::regex _rgx;
	http_handler_t _cb;
};

class http_server;
struct router_family
{
public:
	router_family(const char* name, boost::regex rgx):
	_family(name),
	_rgx(rgx),
	_http_server(nullptr)
	{

	}

	router_family& regist_router(router_child* child)
	{
		_router_child.push_back(router_child::ptr(child));
		return *this;
	}
	router_child::ptr rout(std::string& url)
	{
		static boost::regex_iterator<std::string::iterator> end;
		boost::regex_iterator<std::string::iterator> it(url.begin(), url.end(), _rgx);
		if (it == end)
			return router_child::ptr();
		url = url.substr(it->length(), url.length()-1);
		for (auto child : _router_child)
		{
			if(child->rout(url))
				return child;
		}
		return router_child::ptr();
	}
private:
public:
	std::string _family;
	boost::regex _rgx;
	std::vector<router_child::ptr> _router_child;

	http_server* _http_server;
};

struct root_router
{
public:
	friend class http_server;
	boost::shared_ptr<router_child> rout(std::string& url)
	{
		std::lock_guard<std::mutex> lock(_mutex);
		router_child::ptr router;
		for (auto family : _router_family)
		{
			if (router = family->rout(url))
				return router;
		}
		return router_child::ptr();;
	}

	void register_router(router_family* router)
	{
		std::lock_guard<std::mutex> lock(_mutex);
		_router_family.push_back(router);
	}
	bool delete_router(const char* name)
	{
		std::lock_guard<std::mutex> lock(_mutex);
		for (auto it = _router_family.begin(); it != _router_family.end(); ++it)
		{
			if ((*it)->_family.compare(name))
				continue;
			it = _router_family.erase(it);
			return true;
		}
		return false;
	}
private:
	std::mutex _mutex;
	std::vector<router_family*> _router_family;
};

#endif // router_h__
